package com.jhws.sys.cms.service;

import com.alibaba.fastjson.JSON;
import com.jhws.business.aliyun.service.OSSClientService;
import com.jhws.sys.cms.bo.CommGroup;
import com.jhws.sys.cms.bo.NodePrivateInfo;
import com.jhws.sys.cms.bo.ResourceType;
import com.jhws.sys.user.bo.TblUserDimBo;
import com.jhws.business.customer.bo.CustomContentInfo;
import com.jhws.util.GetId;
import com.jhws.common.base.bo.Global;
import com.jhws.common.Page;
import com.jhws.core.db.BaseDao;
import com.jhws.core.exception.BizException;
import com.jhws.sys.user.service.ITblUserDimService;
import com.jhws.util.ObjectUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.*;

@SuppressWarnings("Duplicates")
@Service
public class AppResourceService {
    @Resource
    private BaseDao BaseDao;
    @Resource
    protected ITblUserDimService userDimService;
    @Resource
    private NodePrivateInfoService nodeAliasesService;
    @Resource
    private OSSClientService ossClientService;

    /**
     * 保存资源，如果有id，则更新
     *
     * @param r
     */
    public void saveResource(com.jhws.sys.cms.bo.Resource r) throws InvocationTargetException, IllegalAccessException {
        if (StringUtils.isBlank(r.getResource_id())) {
            r.setResource_id(GetId.randomID());
            r.setCreate_time(new Date());
            BaseDao.h().save(r);
        } else {
            if (StringUtils.isEmpty(r.getIcon_url())) {
                String iconUrl = BaseDao.j().queryForObject("select icon_url from cms_resource where resource_id='" + r.getResource_id() + "'", String.class);
                r.setIcon_url(iconUrl);
            }
            BaseDao.h().update(r);
        }
    }

    /**
     * @param ResourceId 资源ID
     * @return 资源
     */
    public com.jhws.sys.cms.bo.Resource queryResourceIdByResource(String ResourceId) {
        if (StringUtils.isEmpty(ResourceId)) {
            return null;
        }
        return BaseDao.get(com.jhws.sys.cms.bo.Resource.class, ResourceId);
    }

    /**
     * 查询自定义类型
     *
     * @param param sortCode
     * @return
     * @throws Exception
     */
    public Map<String, Object> queryResourceCustomType(Map param) throws Exception {
        boolean isPage = MapUtils.getBooleanValue(param, "isPage");
        String customTypeId = MapUtils.getString(param, "customTypeId");
        String type = MapUtils.getString(param, "type");
        boolean isAnalysisCustomContent = MapUtils.getBooleanValue(param, "isAnalysisCustomContent");
        String sql = "SELECT\n" + "	a.custom_type_id,\n" + "	a.custom_type_code,\n"
                + "	a.custom_type_name,\n" + "	a.custom_content,\n" + "	a.description\n"
                + " FROM cms_resource_custom_type a" + " WHERE 1=1 ";
        if (StringUtils.isNotEmpty(customTypeId)) {
            sql += "and custom_type_id in (" + com.jhws.util.StringUtils.spilt(customTypeId) + ")";
        }
        if (StringUtils.isNotEmpty(type)) {
            sql += "and type = '" + type + "'";
        }
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> list;
        if (isPage) {
            Page p = BaseDao.queryPage(sql, Map.class);
            list = p.getList();
            result.put("size", p.getTotalNumber());
        } else {
            list = BaseDao.j().queryForList(sql);
        }
        if (isAnalysisCustomContent) {
            for (Map<String, Object> o : list) {
                String customContent = MapUtils.getString(o, "custom_content");
                if (StringUtils.isNotEmpty(customContent)) {
                    List<CustomContentInfo> customContentInfos = JSON.parseArray(customContent, CustomContentInfo.class);
                    o.put("customContents", customContentInfos);
                }
            }
        }
        result.put("list", list);
        return result;
    }

    /**
     * 条件查询资源列表
     *
     * @param where 条件
     * @return
     */
    public List<com.jhws.sys.cms.bo.Resource> queryResourceByWhere(String where) {
        return BaseDao.findList("from cms_resource " + where);
    }

    /**
     * 查询资源列表
     *
     * @param param （type_id，type_name）
     * @return
     * @throws IOException
     */
    public Map<String, Object> queryResourcePage(Map param) throws IOException {
        TblUserDimBo userBo = userDimService.currentUser();
        String typeCode = MapUtils.getString(param, "type_code", "");
        //是否查询默认小区数据
        boolean isDefQueryResource = MapUtils.getBooleanValue(param, "isDefQueryResource");
        boolean includeSub = MapUtils.getBooleanValue(param, "includeSub");
        boolean isAllUserResource = MapUtils.getBooleanValue(param, "isAllUserResource");
        String typeIdCondition = includeSub(includeSub, typeCode);
        String sql = "SELECT\n" + "	a.resource_id,\n" + "	b.type_name,\n" + "	a.title,\n" + "	a.icon_url,\n"
                + "	a.content_url,\n" + "	a.create_time,\n" + "	a.creator,\n" + "	a.type_code,\n" + "	a.parentResourceId,\n"
                + "	a.isApproved,\n" + "	a.approvedState,\n" + "	a.comm_code,\n" + "	a.customContent,\n" + "	a.description\n" + "FROM\n"
                + "	cms_resource a,\n" + "	cms_resource_type b\n" + "WHERE\n" + "	a.type_code = b.type_code ";
        String isApproved = MapUtils.getString(param, "isApproved", "");
        if (!StringUtils.isEmpty(isApproved)) {
            if (isApproved.length() == 1) {
                sql += " and a.isApproved = '" + isApproved + "' ";
            } else {
                sql += " and a.isApproved in (" + com.jhws.util.StringUtils.spilt(isApproved) + ") ";
            }
        }
        sql += typeIdCondition;
        String commGroupId = MapUtils.getString(param, "commGroupId", "");
        String commCode = MapUtils.getString(param, "commCode", "");
        //查询只能是当前帐号录制的资源，对默认小区特殊处理,只要查询默认资源表示是分配界面查询
        if (isDefQueryResource) {
            if (!Global.DEFAULT_COMM.equals(commCode)) {
                //如果是admin权限又不是默认小区只查询也分配资源
                if (SecurityUtils.getSubject().hasRole(Global.ROLE_SUPPER_ADMIN)) {
                    if (StringUtils.isEmpty(commGroupId) && StringUtils.isEmpty(commCode)) {
                        throw new BizException("小区编号或小区分组ID不能为空！");
                    } else if (StringUtils.isNotEmpty(commGroupId) && StringUtils.isNotEmpty(commCode)) {
                        throw new BizException("不能同时查询小区资源和分组资源！");
                    }
                    if (StringUtils.isNotEmpty(commGroupId)) {
                        sql += " and a.commGroupId='" + commGroupId + "'";
                    }
                    if (StringUtils.isNotEmpty(commCode)) {
                        sql += " and a.comm_code='" + commCode + "'";
                    }
                } else {
                    sql += " and ((a.creator = '" + userBo.getLogName() + "' and a.commGroupId is null and a.comm_code is null) or a.comm_code = '" + Global.DEFAULT_COMM + "')";
                }
            } else {
                sql += " and a.commGroupId is null and a.comm_code is null and a.creator = '" + userBo.getLogName() + "'";
            }
        } else if (isAllUserResource) {
            sql += " and a.commGroupId is null and a.comm_code is null ";
        } else {
            sql += " and a.commGroupId is null and a.comm_code is null and a.creator = '" + userBo.getLogName() + "'";
        }

        sql += " order by a.create_time desc";
        Page p = BaseDao.queryPage(sql, Map.class);
        List<Map<String, Object>> list = p.getList();
        for (Map<String, Object> map : list) {
            String objUrl = (String) map.get("icon_url");
            String url = ossClientService.getUrl(objUrl, false);
            if (!StringUtils.isEmpty(url) && !url.equals(objUrl)) {
                map.replace("icon_url", url);
            }
        }
        Map<String, Object> result = new HashMap<>();
        result.put("list", list);
        result.put("size", p.getTotalNumber());
        return result;
    }

    /**
     * 查询已分配资源列表
     *
     * @param param （type_id，type_name）
     * @return
     * @throws IOException
     */
    public Map<String, Object> queryAlreadyResource(Map param) throws IOException {
        String typeCode = MapUtils.getString(param, "type_code", "");
        boolean includeSub = MapUtils.getBooleanValue(param, "includeSub");
        String typeIdCondition = includeSub(includeSub, typeCode);
        String sql = "SELECT\n" + "	a.resource_id,\n" + "	b.type_name,\n" + "	a.title,\n" + "	a.icon_url,\n"
                + "	a.content_url,\n" + "	a.create_time,\n" + "	a.creator,\n" + "	a.type_code,\n"
                + "	a.isApproved,\n" + "	a.approvedState,\n" + "	a.comm_code,\n" + "a.parentResourceId,\n" + "	a.description\n" + "FROM\n"
                + "	cms_resource a,\n" + "	cms_resource_type b\n" + "WHERE\n" + "	a.type_code = b.type_code ";
        sql += typeIdCondition;
        Map<String, Object> result = new HashMap<>();
        //如果有组id表示需要查询已经分好组的资源
        List<Map<String, Object>> list;
        String commGroupId = MapUtils.getString(param, "commGroupId", "");
        String commCode = MapUtils.getString(param, "commCode", "");

        if (StringUtils.isEmpty(commGroupId) && StringUtils.isEmpty(commCode)) {
            throw new BizException("小区编号或小区分组ID不能为空！");
        } else if (StringUtils.isNotEmpty(commGroupId) && StringUtils.isNotEmpty(commCode)) {
            throw new BizException("不能同时查询小区资源和分组资源！");
        }
        if (StringUtils.isNotEmpty(commGroupId)) {
            sql += " and a.commGroupId='" + commGroupId + "'";
        }
        if (StringUtils.isNotEmpty(commCode)) {
            sql += " and a.comm_code='" + commCode + "'";
        }
        sql += " order by a.create_time desc";
        list = BaseDao.j().queryForList(sql);
        for (Map<String, Object> map : list) {
            String objUrl = (String) map.get("icon_url");
            String url = ossClientService.getUrl(objUrl, false);
            if (!StringUtils.isEmpty(url) && !url.equals(objUrl)) {
                map.replace("icon_url", url);
            }
        }
        result.put("list", list);
        result.put("ret_code", 1);
        return result;
    }

    /**
     * 查询资源列表api返回数据使用
     *
     * @param typeCode （typeCode）
     * @return
     * @throws IOException
     */
    public List<Map<String, Object>> queryResourceListApi(String typeCode, List<CommGroup> groupList, String commCode) throws IOException {
        return queryResourceRecursions(typeCode, groupList, commCode);
    }

    /**
     * @param typeCode  资源code
     * @param groupList 小区组
     * @param commCode  小区编号
     * @return
     * @throws IOException
     */
    private List<Map<String, Object>> queryResourceRecursions(String typeCode, List<CommGroup> groupList, String commCode) throws IOException {
        String hql = "from ResourceType where 1=1 and parent_code='" + typeCode + "' order by sortEncoding asc";
        List<ResourceType> resourceTypes = BaseDao.findList(hql);
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (ResourceType resourceType : resourceTypes) {
            Map<String, Object> types = new HashedMap();
            List<Map<String, Object>> tempMap = queryResourceRecursions(resourceType.getType_code(), groupList, commCode);

            Map<String, String> param = new HashMap();
            param.put("parentCode", resourceType.getParent_code());
            param.put("typeCode", resourceType.getType_code());
            param.put("commCode", commCode);
            NodePrivateInfo nodePrivateInfo = nodeAliasesService.queryNodePrivateInfo(param);

            int nodeSize = tempMap.size();
            if (nodeSize > 0) {
                types.put("type", resourceType.getType_code());
                types.put("node", tempMap);
            } else {
                List<Map<String, Object>> list = queryNodeResourceApi(resourceType.getType_code(), groupList, commCode);
                if (list != null && list.size() > 0) {
                    for (Map<String, Object> o : list) {
                        String customContent = MapUtils.getString(o, "customContent");
                        if (!org.apache.commons.lang.StringUtils.isEmpty(customContent)) {
                            List<CustomContentInfo> customContentInfos = JSON.parseArray(customContent, CustomContentInfo.class);
                            o.put("customContent", customContentInfos);
                        }
                    }
                    types.put("type", resourceType.getType_code());
                    types.put("resource", list);
                } else if (nodePrivateInfo == null || nodePrivateInfo.getUnreadDefComm() == 0) {
                    list = queryNodeResourceApi(resourceType.getType_code(), groupList, Global.DEFAULT_COMM);
                    if (list != null && list.size() > 0) {
                        for (Map<String, Object> o : list) {
                            String customContent = MapUtils.getString(o, "customContent");
                            if (!org.apache.commons.lang.StringUtils.isEmpty(customContent)) {
                                List<CustomContentInfo> customContentInfos = JSON.parseArray(customContent, CustomContentInfo.class);
                                o.put("customContent", customContentInfos);
                            }
                        }
                        types.put("type", resourceType.getType_code());
                        types.put("resource", list);
                    }
                }
                if ((list == null || list.size() <= 0)) {
                    continue;
                }
            }
            //私有別名
            if (nodePrivateInfo != null) {
                types.put("typeName", nodePrivateInfo.getAliases());
            } else {
                types.put("typeName", resourceType.getType_name());
            }
            //私有属性
            if (nodePrivateInfo != null && StringUtils.isNotEmpty(nodePrivateInfo.getCustomProperty())) {
                Map<String, Object> customPropertyInfos = JSON.parseObject(nodePrivateInfo.getCustomProperty(), Map.class);
                for (String key : customPropertyInfos.keySet()) {
                    types.put(key, customPropertyInfos.get(key));
                }
            }
            if (StringUtils.isNotEmpty(resourceType.getCustomProperty())) {
                List<CustomContentInfo> customPropertyInfos = JSON.parseArray(resourceType.getCustomProperty(), CustomContentInfo.class);
                for (CustomContentInfo customContentInfo : customPropertyInfos) {
                    types.put(customContentInfo.getCustomKey(), customContentInfo.getCustomValue());
                }
            }
            mapList.add(types);
        }
        return mapList;
    }

    private List<Map<String, Object>> queryNodeResourceApi(String typeCode, List<CommGroup> groupList, String commCode) {
        String sql = "SELECT\n" + "	a.title,\n" + "	a.icon_url,\n"
                + "	a.content_url,\n" + " a.description,\n" + " a.customType,\n" + " a.customContent\n" + " FROM\n"
                + "	cms_resource a\n" + " WHERE a.type_code ='" + typeCode + "' and a.isApproved='" + Global.CMS_APPROVED + "' ";

        if ((groupList == null || groupList.size() <= 0) && StringUtils.isEmpty(commCode)) {
            return null;
        } else if (groupList != null && groupList.size() > 0 && StringUtils.isNotEmpty(commCode)) {
            List<String> commGroupIds = new ArrayList<>();
            for (CommGroup commGroup : groupList) {
                commGroupIds.add(commGroup.getParentGroupId());
            }
            String sqlGroupIds = com.jhws.util.StringUtils.spilt(commGroupIds);
            sql += " and (a.commGroupId in (" + sqlGroupIds + ") or a.comm_code='" + commCode + "')";
        } else if (StringUtils.isNotEmpty(commCode)) {
            sql += " and a.comm_code='" + commCode + "'";
        } else if (groupList != null && groupList.size() > 0) {
            List<String> commGroupIds = new ArrayList<>();
            for (CommGroup commGroup : groupList) {
                commGroupIds.add(commGroup.getParentGroupId());
            }
            String sqlGroupIds = com.jhws.util.StringUtils.spilt(commGroupIds);
            sql += " and a.commGroupId in (" + sqlGroupIds + ")";
        } else {
            return null;
        }

        sql += " group by a.parentResourceId";
        List<Map<String, Object>> list = BaseDao.j().queryForList(sql);
        for (Map<String, Object> map : list) {
            String objUrl = (String) map.get("icon_url");
            String url = ossClientService.getUrl(objUrl, false);
            if (!StringUtils.isEmpty(url) && !url.equals(objUrl)) {
                map.replace("icon_url", url);
            }
        }
        return list;
    }

    /**
     * 拷贝更新资源
     *
     * @param resourceIds 选中的资源ID
     * @param commGroupId 小区组ID
     * @throws Exception
     */
    public void updateResource(String typeCode, String[] resourceIds, String commGroupId, String commCode) throws Exception {
        if (StringUtils.isEmpty(commGroupId) && StringUtils.isEmpty(commCode)) {
            throw new BizException("小区编号或小区分组ID不能为空！");
        } else if (StringUtils.isNotEmpty(commGroupId) && StringUtils.isNotEmpty(commCode)) {
            throw new BizException("不能同时分配小区资源和分组资源！");
        }
        String typeSql = "";
        String where = "where type_code = '" + typeCode + "' ";
        if (StringUtils.isNotEmpty(commGroupId)) {
            where += " and commGroupId='" + commGroupId + "'";
            typeSql = "'" + commGroupId + "' as commGroupId, null";
        }
        if (StringUtils.isNotEmpty(commCode)) {
            where += " and comm_code='" + commCode + "'";
            typeSql = "null,'" + commCode + "' as comm_code ";
        }
        //先删除原有资源
        deleteResource(where);
        if (resourceIds != null && resourceIds.length > 0) {
            for (String resourceId : resourceIds) {
                String sql = "insert into cms_resource(resource_id,content_url,create_time,description,"
                        + "icon_url,title,creator,type_code,isApproved, customType,customContent,parentResourceId,commGroupId, comm_code)"
                        + " select '" + GetId.GetId2() + "' as resource_id,content_url,create_time,description,icon_url,title,creator, "
                        + " type_code,isApproved, customType,customContent,resource_id," + typeSql + " from cms_resource where resource_id='" + resourceId + "'";
                BaseDao.j().execute(sql);
            }
        }
    }

    /**
     * 拷贝更新资源
     *
     * @param resourceId  选中的资源ID
     * @param commGroupId 小区组ID
     * @throws Exception
     */
    public void updateResource(String typeCode, String resourceId, String commGroupId, String commCode, boolean isAssigns) throws Exception {
        if (StringUtils.isEmpty(resourceId)) {
            throw new BizException("资源选择错误！");
        }
        if (StringUtils.isEmpty(commGroupId) && StringUtils.isEmpty(commCode)) {
            throw new BizException("小区编号或小区分组ID不能为空！");
        } else if (StringUtils.isNotEmpty(commGroupId) && StringUtils.isNotEmpty(commCode)) {
            throw new BizException("不能同时分配小区资源和分组资源！");
        }
        com.jhws.sys.cms.bo.Resource resource = queryResourceIdByResource(resourceId);
        if (StringUtils.isNotEmpty(resource.getComm_code()) && Global.DEFAULT_COMM.equals(resource.getComm_code())) {
            resourceId = resource.getParentResourceId(); //如果分配的是默认小区资源，必须找到父ID
        }
        String typeSql = "";
        String where = "where parentResourceId ='" + resourceId + "' and type_code = '" + typeCode + "' ";
        if (!Global.DEFAULT_COMM.equals(commCode) || isAssigns) {//如果是默认小区
            if (StringUtils.isNotEmpty(commGroupId)) {
                where += " and commGroupId='" + commGroupId + "'";
                typeSql = "'" + commGroupId + "' as commGroupId, null";
            }
            if (StringUtils.isNotEmpty(commCode)) {
                where += " and comm_code='" + commCode + "'";
                typeSql = "null,'" + commCode + "' as comm_code ";
            }
        }
        //先删除原有资源
        deleteResource(where);
        if (isAssigns) {
            String sql = "insert into cms_resource(resource_id,content_url,create_time,description,"
                    + "icon_url,title,creator,type_code,isApproved, customType,customContent,parentResourceId,commGroupId, comm_code)"
                    + " select '" + GetId.GetId2() + "' as resource_id,content_url,create_time,description,icon_url,title,creator, "
                    + " type_code,isApproved, customType,customContent,resource_id," + typeSql + " from cms_resource where resource_id='" + resourceId + "'";
            BaseDao.j().execute(sql);
        }
    }

    /**
     * 更新资源
     *
     * @param set
     * @param where
     */
    public void updateResource(String set, String where) {
        String sql = "update cms_resource " + set + where;
        BaseDao.j().execute(sql);
    }

    /**
     * 条件删除资源
     *
     * @param where 条件
     */
    public void deleteResource(String where) {
        String sql = "delete from cms_resource " + where;
        BaseDao.j().execute(sql);
    }

    /**
     * 删除oss上的资源同时就要删除所有相应的资源记录
     *
     * @param key ossKey
     */
    public void deleteRemoteFile(com.jhws.sys.cms.bo.Resource r, String key) {
        String sql = null;
        if (StringUtils.isNotEmpty(key)) {
            ossClientService.deleteObject(key);
            sql = "delete from cms_resource where icon_url = '" + key + "' ";
        }

        if (StringUtils.isNotEmpty(r.getResource_id())) {
            if (StringUtils.isNotEmpty(sql)) {
                sql += " or resource_id='" + r.getResource_id() + "' or parentResourceId='" + r.getResource_id() + "'";
            } else {
                sql = "delete from cms_resource where resource_id='" + r.getResource_id() + "' or parentResourceId='" + r.getResource_id() + "'";
            }
        }
        BaseDao.j().execute(sql);
    }


    /**
     * @param includeSub true 父节点开始查询
     * @param typeCode   资源类型
     * @return
     */
    private String includeSub(boolean includeSub, String typeCode) {
        StringBuilder typeIdCondition = new StringBuilder();
        if (StringUtils.isNotBlank(typeCode)) {
            if (includeSub) {
                List<String> subTypeIds = new ArrayList<>();
                queryChildCode(subTypeIds, typeCode);
                if (CollectionUtils.isNotEmpty(subTypeIds)) {
                    typeIdCondition = new StringBuilder(" and a.type_code in ('" + typeCode + "'");
                    for (String id : subTypeIds) {
                        typeIdCondition.append(",'").append(id).append("'");
                    }
                    typeIdCondition.append(") ");
                } else {
                    typeIdCondition = new StringBuilder(" and a.type_code = '" + typeCode + "' ");
                }
            } else {
                typeIdCondition = new StringBuilder(" and a.type_code = '" + typeCode + "' ");
            }
        }
        return typeIdCondition.toString();
    }

    //递归查询子类
    private void queryChildCode(List<String> typeCodes, String parentCode) {
        List<String> subTypeIds = BaseDao.j().queryForList(
                "select type_code from cms_resource_type where parent_code = ?", String.class, parentCode);
        if (CollectionUtils.isNotEmpty(subTypeIds)) {
            typeCodes.addAll(subTypeIds);
            for (String typeCode : subTypeIds) {
                queryChildCode(typeCodes, typeCode);
            }
        }
    }
}
